home *** CD-ROM | disk | FTP | other *** search
/ Sky at Night 2006 September / SAN CD 9-2006 CD-ROM 16.iso / pc / Software / Network Telescope Control / NTC-Setup.Exe / Source / ntc_server_comms.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2006-03-24  |  62.7 KB  |  2,522 lines

  1. unit ntc_server_comms;
  2. {
  3.     Copyright (C) 2004 - 2006 Andrew Sprott
  4.  
  5.     http://astronomy.crysania.co.uk
  6.     astro@trefach.co.uk
  7.  
  8.     This program is free software; you can redistribute it and/or
  9.     modify it under the terms of the GNU General Public License
  10.     as published by the Free Software Foundation; either version 2
  11.     of the License, or (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; if not, write to the Free Software
  20.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. }
  22.  
  23. interface
  24.  
  25. uses
  26.     Windows,
  27.     Messages,
  28.     SysUtils,
  29.     Variants,
  30.     Classes,
  31.     Graphics,
  32.     Controls,
  33.     Forms,
  34.     Dialogs,
  35.     StdCtrls,
  36.     ExtCtrls,
  37.     inifiles,
  38.  
  39.     ntc_server_form,
  40.     ntc_server_object;
  41.  
  42. const
  43.     { scope response timeout [5 seconds default] }
  44.     response_timeout=5000;
  45.     { io handing }
  46.     max_buffer_size=4096;
  47.     in_buffer_size=max_buffer_size;
  48.     out_buffer_size=max_buffer_size;
  49.     { port handling }
  50.  
  51.     north=0;
  52.     south=1;
  53.     east=2;
  54.     west=3;
  55.  
  56.     invalid_reading=65535;
  57.  
  58.     { meade }
  59.     hms_s=8;    { HH:MM:SS }
  60.     hmt_s=7;    { HH:MM.T# }
  61.     ams_s=9;    { sDD*MMíSS }
  62.     am_s=6;        { sDD*MM }
  63.     dms_s=9;    { sDD*MMíSS }
  64.     dm_s=8;        { sDD*MM }
  65.     ddms_s=9;    { DDD*MMíSS }
  66.     ddmt_s=8;    { DDD*MM#T }
  67.  
  68.     { celestron }
  69.     hex_16=4;
  70.     hex_16_r=65536;
  71.     hex_32=8;
  72.     hex_32_r=4294967296;
  73.  
  74.     max_speeds=2;
  75.  
  76. type
  77.     short=array[1..2] of byte;
  78.     long=array[1..4] of byte;
  79.  
  80.     p_command_record=^command_record;
  81.     command_record=record
  82.         last_command,
  83.         next_command:p_command_record;
  84.         command,
  85.         scope_write:string;
  86.         appends,
  87.         returns:boolean;
  88.         in_text_1,
  89.         in_text_2:string[64];
  90.         out_text_1,
  91.         out_text_2:string[32];
  92.         default_string:string;
  93.     end;
  94.  
  95.     buffer_type=array[1..max_buffer_size] of byte;
  96.  
  97.     Tscope_comms = class(tform)
  98.         comms_panel: TPanel;
  99.         port_group: TGroupBox;
  100.         serial_label: TLabel;
  101.         speed_label: TLabel;
  102.         parity_label: TLabel;
  103.         bits_label: TLabel;
  104.         stop_bits_label: TLabel;
  105.         timeout_label: TLabel;
  106.         interval_label: TLabel;
  107.         speed_edit: TComboBox;
  108.         port_edit: TComboBox;
  109.         parity_edit: TComboBox;
  110.         data_bits_edit: TComboBox;
  111.         stop_bits_edit: TComboBox;
  112.         timeout_edit: TComboBox;
  113.         interval_edit: TComboBox;
  114.         response_timer: TTimer;
  115.  
  116.         { form handling }
  117.         procedure formcreate(
  118.             Sender:TObject);
  119.  
  120.         procedure kill;
  121.  
  122.         { configuration }
  123.         procedure load_settings;
  124.  
  125.         procedure save_settings;
  126.  
  127.         procedure read_escape_scopes;
  128.  
  129.         procedure create_command_record(
  130.             name,
  131.             out_string:string;
  132.             does_append:boolean;
  133.             out_1,
  134.             out_2:string;
  135.             does_return:boolean;
  136.             in_1,
  137.             in_2,
  138.             string_that_is_default:string);
  139.  
  140.         { events }
  141.         procedure FormShow(
  142.             Sender: TObject);
  143.  
  144.         procedure adjust;
  145.  
  146.         procedure check_activate(
  147.             Sender: TObject);
  148.  
  149.         { scope connecting }
  150.         Function connect_to_scope
  151.             :boolean;
  152.  
  153.         Function disconnect_from_scope
  154.             :boolean;
  155.  
  156.         { communications }
  157.         Function open
  158.             :boolean;
  159.  
  160.         Procedure close;
  161.  
  162.         Function read(
  163.             default_string:string)
  164.             :response_type;
  165.  
  166.         Function read_timeout(
  167.             default_string:string)
  168.             :boolean;
  169.  
  170.         Function write(
  171.             b:string)
  172.             :boolean;
  173.  
  174.         Procedure clear_port;
  175.  
  176.         { scope commands }
  177.         function tell(
  178.                     message_text:string;
  179.             var return_object:tscope_object)
  180.             :string;
  181.  
  182.         { logging }
  183.         Procedure init_log_file(
  184.             s:string);
  185.  
  186.         Procedure write_log(
  187.             e:string);
  188.  
  189.         procedure update_status_log(
  190.             m:string);
  191.  
  192.         Procedure close_log;
  193.  
  194.         procedure form_close_query(
  195.                     Sender: TObject;
  196.             var CanClose: Boolean);
  197.  
  198.         procedure timeout_editChange(
  199.             Sender: TObject);
  200.  
  201.         procedure interval_editChange(
  202.             Sender: TObject);
  203.  
  204.         procedure response_timerTimer(
  205.             Sender: TObject);
  206.  
  207.     private
  208.         { Private declarations }
  209.         scope_handle:thandle;
  210.         port_file_open:boolean;
  211.         { logging }
  212.         log_handle:textfile;
  213.         log_filename:string;
  214.         { io }
  215.         port:string;
  216.         timeout,
  217.         interval:longint;
  218.         response_timed_out:boolean;
  219.         command_last,
  220.         first_command:p_command_record;
  221.         work_buffer:buffer_type;
  222.         wb_size:integer;
  223.     public
  224.         { Public declarations }
  225.         command_list:tstringlist;
  226.         precision_format:integer;
  227.         port_opened,
  228.         scope_connected:boolean;
  229.         { configuration }
  230.         dimensions:dimensions_record;
  231.         { logging }
  232.         message_logging,
  233.         io_logging,
  234.         file_logging:boolean;
  235.  
  236.         { events }
  237.         procedure check_visible_and_show_hide(
  238.             sender:tobject);
  239.  
  240.         procedure hide_form;
  241.         procedure show_form;
  242.     end;
  243.  
  244. var
  245.     scope_comms: Tscope_comms;
  246.  
  247. implementation
  248.  
  249. uses
  250.     ntc_server_info,
  251.     ntc_server_network,
  252.     ntc_server_control,
  253.     ntc_server_config,
  254.     ntc_server_search,
  255.     ntc_server_focus;
  256.  
  257. {$R *.dfm}
  258.  
  259.     { -------------
  260.         form handling
  261.         ------------- }
  262.  
  263. procedure tscope_comms.formcreate(
  264.     Sender:TObject);
  265. begin
  266.     port_file_open:=false;
  267.     response_timer.enabled:=false;
  268.     response_timed_out:=false;
  269.     load_settings;
  270.     if message_logging then
  271.         scope_comms.init_log_file('ntc.log');
  272. end;
  273.  
  274. procedure tscope_comms.kill;
  275. begin
  276.     if port_opened then
  277.         begin
  278.             disconnect_from_scope;
  279.             port_opened:=false;
  280.         end;
  281. end;
  282.  
  283.     { -------
  284.         logging
  285.         ------- }
  286.  
  287. Procedure tscope_comms.init_log_file(
  288.     s:string);
  289. var
  290.     io:integer;
  291. begin
  292.     try
  293.         log_filename:=application_path+s;
  294.         {$I-}
  295.         assignfile(log_handle,log_filename);
  296.         {$I+}
  297.         io:=ioresult;
  298.         if io=0 then
  299.             begin
  300.                 rewrite(log_handle);
  301.                 writeln(log_handle,DateTimeToStr(now)+' : session started');
  302.                 close_log;
  303.             end
  304.         else
  305.             update_status_log('cant create log file : '+log_filename);
  306.     except
  307.         on err:exception do
  308.             begin
  309.                 update_status_log('failed to open log : '+err.message);
  310.             end;
  311.     end;
  312. end;
  313.  
  314. Procedure tscope_comms.write_log(
  315.     e:string);
  316. var
  317.     io:integer;
  318. begin
  319.     if message_logging then
  320.         begin
  321.             try
  322.                 {$I-}
  323.                 assignfile(log_handle,log_filename);
  324.                 {$I+}
  325.                 io:=ioresult;
  326.                 if io=0 then
  327.                     begin
  328.                         append(log_handle);
  329.                         writeln(log_handle,FormatDateTime('hh:mm:ss.zzz',now)+' : '+e);
  330.                         close_log;
  331.                     end
  332.                 else
  333.                     update_status_log('cant open log : '+log_filename);
  334.             except
  335.                 on err:exception do
  336.                     begin
  337.                         update_status_log('failed to write to log : '+err.message);
  338.                         close_log;
  339.                     end
  340.             end;
  341.         end;
  342. end;
  343.  
  344. Procedure tscope_comms.close_log;
  345. var
  346.     io:integer;
  347. begin
  348.     try
  349.         {$I-}
  350.         closefile(log_handle);
  351.         {$I+}
  352.         io:=ioresult;
  353.         if io<>0 then
  354.             update_status_log('failed to close : '+log_filename+' : '+inttostr(io));
  355.     except
  356.         on err:exception do
  357.             update_status_log('failed to close log : '+err.message);
  358.     end;
  359. end;
  360.  
  361. procedure tscope_comms.update_status_log(
  362.     m:string);
  363. begin
  364.     if io_logging then
  365.         scope_network.update_status_log_check(m);
  366. end;
  367.  
  368.     { -------------
  369.         communication
  370.         ------------- }
  371.  
  372. Function tscope_comms.open
  373.     :boolean;
  374. var
  375.     t:tcommtimeouts;
  376.     dcb:tdcb;
  377.     e,c:String;
  378. begin
  379.     update_status_log('open >>');
  380.     result:=false;
  381.     port:=port_edit.text;
  382.     timeout:=strtointdef(timeout_edit.text,1000);
  383.     interval:=strtointdef(interval_edit.text,100);
  384.     c:='baud='+speed_edit.text+
  385.         ' parity='+parity_edit.text[1]+
  386.         ' data='+data_bits_edit.text+
  387.         ' stop='+stop_bits_edit.text;
  388.     update_status_log(
  389.         'connect_to_serial_port : '+port+' '+c+' : '+
  390.         timeout_edit.text+' '+interval_edit.text);
  391.     if port_file_open then
  392.         close;
  393.     scope_handle:=CreateFile(
  394.         PChar(port),
  395.         generic_write or generic_read,
  396.         0,
  397.         nil,
  398.         open_existing,
  399.         file_attribute_normal,
  400.         0);
  401.     if scope_handle<>invalid_handle_value then
  402.         begin
  403.             port_file_open:=true;
  404.             if not SetupComm(scope_handle,in_buffer_size,out_buffer_size) then
  405.                 e:='setupcom failed'
  406.             else if not GetCommState(scope_handle,dcb) then
  407.                 e:='getcommstate failed'
  408.             else if not BuildCommdcb(PChar(c),dcb) then
  409.                 e:='buildcommdcb failed'
  410.             else if not SetCommState(scope_handle,dcb) then
  411.                 e:='setcomstate failed'
  412.             else
  413.                 e:='';
  414.             if e<>'' then
  415.                 update_status_log(e)
  416.             else
  417.                 begin
  418.                     { set timeouts }
  419.                     t.ReadIntervalTimeout:=interval;
  420.                     t.ReadTotalTimeoutMultiplier:=0;
  421.                     t.ReadTotalTimeoutConstant:=timeout;
  422.                     t.WriteTotalTimeoutMultiplier:=0;
  423.                     t.WriteTotalTimeoutConstant:=timeout;
  424.                     SetCommTimeouts(scope_handle,t);
  425.                     result:=true;
  426.                     clear_port;
  427.                     update_status_log(port+' : opened');
  428.                 end;
  429.         end;
  430.     update_status_log('<< open');
  431. end;
  432.  
  433. Procedure tscope_comms.close;
  434. begin
  435.     CloseHandle(scope_handle);
  436.     port_file_open:=false;
  437.     update_status_log(port+' : closed');
  438. end;
  439.  
  440. Procedure tscope_comms.clear_port;
  441. var
  442.     t:TCOMMTIMEOUTS;
  443. begin
  444.     update_status_log('clear_port >>');
  445.     if scope_config.scope_enabled then
  446.         begin
  447.             t.ReadIntervalTimeout:=10;
  448.             t.ReadTotalTimeoutMultiplier:=0;
  449.             t.ReadTotalTimeoutConstant:=10;
  450.             t.WriteTotalTimeoutMultiplier:=0;
  451.             t.WriteTotalTimeoutConstant:=timeout;
  452.             SetCommTimeouts(scope_handle,t);
  453.             try
  454.                 read('');
  455.             finally
  456.                 update_status_log('cleared port');
  457.                 t.ReadIntervalTimeout:=interval;
  458.                 t.ReadTotalTimeoutMultiplier:=0;
  459.                 t.ReadTotalTimeoutConstant:=timeout;
  460.                 t.WriteTotalTimeoutMultiplier:=0;
  461.                 t.WriteTotalTimeoutConstant:=timeout;
  462.                 SetCommTimeouts(scope_handle,t);
  463.             end;
  464.         end;
  465.     update_status_log('<< clear_port');
  466. end;
  467.  
  468. Function tscope_comms.read(
  469.     default_string:string)
  470.     :response_type;
  471. var
  472.     c,n:Cardinal;
  473.     io:integer;
  474.     s:array[1..max_buffer_size] of byte;
  475.     i,r:integer;
  476. begin
  477.     update_status_log('read >>');
  478.     wb_size:=0;
  479.     work_buffer[1]:=0;
  480.     r:=0;
  481.     for i:=1 to max_buffer_size do
  482.         s[i]:=0;
  483.     result:=[exit_ok];
  484.     if port_opened then
  485.         begin
  486.             if scope_config.scope_enabled then
  487.                 begin
  488.                     repeat
  489.                         n:=0;
  490.                         c:=max_buffer_size;
  491.                         {$I-}
  492.                         ReadFile(scope_handle,pchar(s[1])^,c,n,nil);
  493.                         {$I+}
  494.                         io:=ioresult;
  495.                         if (io=0) and (n<>0) then
  496.                              for i:=1 to n do
  497.                             begin
  498.                                 work_buffer[i+r]:=s[i];
  499.                                 inc(r,n);
  500.                             end;
  501.                     until (io<>0) or (n=0);
  502.                     wb_size:=r;
  503.                     work_buffer[wb_size+1]:=0;
  504.                     if io<>0 then
  505.                         begin
  506.                             update_status_log('read : error : '+inttostr(io));
  507.                             close;
  508.                             result:=[exit_fail];
  509.                         end
  510.                     else
  511.                         begin
  512.                             update_status_log(
  513.                                 'Read : '+inttostr(r)+' : '+pchar(work_buffer[1]));
  514.                             if r=0 then
  515.                                 result:=[exit_void];
  516.                         end;
  517.                 end
  518.             else for i:=1 to length(default_string) do
  519.                 work_buffer[i]:=byte(default_string[i]);
  520.         end
  521.     else if scope_config.scope_enabled then
  522.         begin
  523.             update_status_log('fail : port not opened');
  524.             result:=[exit_fail];
  525.         end
  526.     else for i:=1 to length(default_string) do
  527.         work_buffer[i]:=byte(default_string[i]);
  528.     update_status_log(pchar(@work_buffer[1])^+' <<  read');
  529. end;
  530.  
  531. Function tscope_comms.read_timeout(
  532.     default_string:string)
  533.     :boolean;
  534. var
  535.     exit_type:response_type;
  536.     done:boolean;
  537. begin
  538.     while response_timer.enabled do
  539.         update_status_log('<< waiting');
  540.     response_timed_out:=false;
  541.     response_timer.interval:=response_timeout;
  542.     response_timer.enabled:=true;
  543.     wb_size:=0;
  544.     done:=false;
  545.     while not done do
  546.         begin
  547.             if not response_timed_out then
  548.                 begin
  549.                     exit_type:=read(default_string);
  550.                     if exit_type*[exit_void]=[] then
  551.                         done:=true
  552.                     else
  553.                         application.processmessages;
  554.                 end
  555.             else
  556.                 begin
  557.                     exit_type:=[exit_fail];
  558.                     done:=true;
  559.                 end;
  560.         end;
  561.     response_timer.enabled:=false;
  562.     result:=exit_type>=[exit_ok];
  563.     response_timed_out:=false;
  564. end;
  565.  
  566. Function tscope_comms.write(
  567.     b:string)
  568.     :boolean;
  569. var
  570.     c,
  571.     n:cardinal;
  572.     e:boolean;
  573.     io:integer;
  574. begin
  575.     update_status_log('write  >> '+b);
  576.     if port_opened then
  577.         begin
  578.             if scope_config.scope_enabled then
  579.                 begin
  580.                     n:=0;
  581.                     c:=length(b);
  582.                     {$i-}
  583.                     e:=writefile(scope_handle,pchar(b)^,c,n,nil);
  584.                     {$i+}
  585.                     io:=ioresult;
  586.                     if not e or (io<>0) then
  587.                         begin
  588.                             update_status_log('write failed : '+inttostr(io));
  589.                             result:=false;
  590.                         end
  591.                     else if c<>n then
  592.                         begin
  593.                             update_status_log('bytes to send : '+inttostr(c));
  594.                             update_status_log('bytes written : '+inttostr(n));
  595.                             result:=false;
  596.                         end
  597.                     else
  598.                         begin
  599.                             update_status_log(b+' : written');
  600.                             result:=true;
  601.                         end;
  602.                 end
  603.             else
  604.                 result:=true;
  605.         end
  606.     else if scope_config.scope_enabled then
  607.         begin
  608.             update_status_log('fail : port not opened');
  609.             result:=false;
  610.         end
  611.     else
  612.         result:=true;
  613.     update_status_log('<< write');
  614. end;
  615.  
  616.     { ----------------
  617.         scope connecting
  618.         ---------------- }
  619.  
  620. Function tscope_comms.connect_to_scope
  621.     :boolean;
  622. var
  623.     p,e:string;
  624. begin
  625.     update_status_log('connect_to_scope >>');
  626.     if scope_config.scope_enabled then
  627.         begin
  628.             result:=false;
  629.             p:=trim(port_edit.text);
  630.             if pos(p,'COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8')=0 then
  631.                 begin
  632.                     e:='Invalid communication port : '+p;
  633.                     update_status_log(e);
  634.                 end
  635.             else
  636.                 begin
  637.                     if port_opened then
  638.                         disconnect_from_scope;
  639.                     if open then
  640.                         begin
  641.                             port_opened:=true;
  642.                             scope_connected:=true;
  643.                             { check scope connected }
  644.                             case scope_config.scope_type of
  645.                                 lx200_type..autostar_type:
  646.                                     begin
  647.                                         p:=tell('get_ra_dec',current_object);
  648.                                         if pos('ok',copy(p,1,2))>0 then
  649.                                             begin
  650.                                                 scope_info.show_info;
  651.                                                 result:=true;
  652.                                             end
  653.                                         else
  654.                                             begin
  655.                                                 result:=false;
  656.                                                 scope_connected:=false;
  657.                                             end;
  658.                                     end;
  659.                                 celestron_type:
  660.                                     begin
  661.                                         p:=tell('query',current_object);
  662.                                         if pos('ok',copy(p,1,2))>0 then
  663.                                             result:=true
  664.                                         else
  665.                                             begin
  666.                                                 result:=false;
  667.                                                 scope_connected:=false;
  668.                                             end;
  669.                                     end;
  670.                              end;
  671.                         end
  672.                     else
  673.                         begin
  674.                             update_status_log('Port '+p+' cannot be opened!');
  675.                             scope_connected:=false;
  676.                         end;
  677.                 end;
  678.         end
  679.     else
  680.         begin
  681.             scope_info.show_info;
  682.             scope_connected:=true;
  683.             result:=true;
  684.         end;
  685.     update_status_log('connect_to_scope >>');
  686. end;
  687.  
  688. Function tscope_comms.disconnect_from_scope
  689.     :boolean;
  690. begin
  691.     if scope_config.scope_enabled then
  692.         begin
  693.             close;
  694.             port_opened:=false;
  695.             scope_connected:=false;
  696.             result:=true;
  697.         end
  698.     else
  699.         begin
  700.             scope_connected:=false;
  701.             result:=true;
  702.         end;
  703.     scope_search.search_timer.enabled:=false;
  704. end;
  705.  
  706.     { -------------
  707.         configuration
  708.         ------------- }
  709.  
  710. procedure tscope_comms.load_settings;
  711. begin
  712.     ini_file:=tinifile.create(application_path+'server.ini');
  713.     with ini_file do
  714.         begin
  715.             timeout_edit.text:=readstring('comms','timeout','100');
  716.             interval_edit.text:=readstring('comms','interval','10');
  717.             with port_edit do
  718.                 begin
  719.                     text:=readstring('comms','comport','COM1');
  720.                     if (length(text)<4) or
  721.                          (strtointdef(text[4],1)>8) then
  722.                         port_edit.text:='COM1';
  723.                 end;
  724.             speed_edit.text:=readstring('comms','baud','9600');
  725.             data_bits_edit.text:=readstring('comms','databits','8');
  726.             parity_edit.text:=readstring('comms','parity','N');
  727.             stop_bits_edit.text:=readstring('comms','stopbits','1');
  728.             io_logging:=readbool('comms','io_logging',false);
  729.             file_logging:=readbool('comms','file_logging',false);
  730.             read_escape_scopes;
  731.             { form }
  732.             scope.get_dimensions(scope_comms,@dimensions,'comms',ini_file);
  733.             left:=dimensions.form_left;
  734.             top:=dimensions.form_top;
  735.             visible:=readbool('comms','visible',false);
  736.         end;
  737.     ini_file.free;
  738. end;
  739.  
  740. procedure tscope_comms.save_settings;
  741. begin
  742.     with ini_file do
  743.         begin
  744.             writestring('comms','timeout',timeout_edit.text);
  745.             writestring('comms','interval',interval_edit.text);
  746.             writestring('comms','comport',port_edit.text);
  747.             writestring('comms','baud',speed_edit.text);
  748.             writestring('comms','databits',data_bits_edit.text);
  749.             writestring('comms','parity',parity_edit.text);
  750.             writestring('comms','stopbits',stop_bits_edit.text);
  751.             WriteInteger('comms','top',top);
  752.             WriteInteger('comms','left',left);
  753.             writeBool('comms','message_logging',message_logging);
  754.             writebool('comms','io_logging',io_logging);
  755.             writebool('comms','file_logging',file_logging);
  756.             { form }
  757.             scope.find_vdu(scope_comms,@dimensions);
  758.             scope.write_dimensions(@dimensions,left,top,'comms',ini_file);
  759.             writebool('comms','visible',visible);
  760.         end;
  761. end;
  762.  
  763. procedure tscope_comms.create_command_record(
  764.     name,
  765.     out_string:string;
  766.     does_append:boolean;
  767.     out_1,
  768.     out_2:string;
  769.     does_return:boolean;
  770.     in_1,
  771.     in_2,
  772.     string_that_is_default:string);
  773. var
  774.     new_command:p_command_record;
  775. begin
  776.     new(new_command);
  777.     with new_command^ do
  778.         begin
  779.             if command_last<>nil then
  780.                 begin
  781.                     command_last.next_command:=new_command;
  782.                     last_command:=command_last;
  783.                 end
  784.             else
  785.                 last_command:=nil;
  786.             next_command:=nil;
  787.             command:=name;
  788.             scope_write:=out_string;
  789.             appends:=does_append;
  790.             returns:=does_return;
  791.             in_text_1:=in_1;
  792.             in_text_2:=in_2;
  793.             out_text_1:=out_1;
  794.             out_text_2:=out_2;
  795.             default_string:=string_that_is_default;
  796.         end;
  797.     command_last:=new_command;
  798. end;
  799.  
  800. procedure Tscope_comms.read_escape_scopes;
  801. var
  802.     ini_file:tinifile;
  803.     command_next:p_command_record;
  804.     i:integer;
  805. begin
  806.     with scope_config do
  807.          if scope_type=lx200_type then
  808.         ini_file:=tinifile.create(application_path+'lx200.ini')
  809.     else if scope_type=autostar_type then
  810.         ini_file:=tinifile.create(application_path+'autostar.ini')
  811.     else
  812.         ini_file:=tinifile.create(application_path+'default.ini');
  813.     with ini_file,scope_config do
  814.          if scope_type=celestron_type then
  815.         begin
  816.             command_last:=nil;
  817.             create_command_record('stopped',
  818.                 readstring('stopped','write','L'),
  819.                 readbool('stopped','append',false),
  820.                 '','',
  821.                 readbool('stopped','returns',true),
  822.                 readstring('stopped','valid','$valid=0#$'),
  823.                 '','0#');
  824.  
  825.             first_command:=command_last;
  826.  
  827.             create_command_record('query',
  828.                 readstring('query','write','?'),
  829.                 readbool('query','append',false),
  830.                 '','',
  831.                 readbool('query','returns',true),
  832.                 readstring('query','valid','$valid=#$'),
  833.                 '','#');
  834.  
  835.             create_command_record('get_ra_dec',
  836.                 readstring('get_ra_dec','write','E'),
  837.                 readbool('get_ra_dec','append',false),
  838.                 '','',
  839.                 readbool('get_ra_dec','returns',true),
  840.                 readstring('get_ra_dec','high','$ra_hex32$,$dec_hex32$#'),
  841.                 readstring('get_ra_dec','low','$ra_hex$,$dec_hex$#'),
  842.                 'ad35,cead#');
  843.  
  844.             create_command_record('get_az_alt',
  845.                 readstring('get_az_alt','write','Z'),
  846.                 readbool('get_az_alt','append',false),
  847.                 '','',
  848.                 readbool('get_az_alt','returns',true),
  849.                 readstring('get_az_alt','high','$az_hex32$,$alt_hex32$#'),
  850.                 readstring('get_az_alt','low','$az_hex$,$alt_hex$#'),
  851.                 '12f3,7698#');
  852.  
  853.             create_command_record('goto_ra_dec',
  854.                 readstring('goto_ra_dec','write','R'),
  855.                 readbool('goto_ra_dec','append',true),
  856.                 readstring('goto_ra_dec','high','$ra_hex32$,$dec_hex32$'),
  857.                 readstring('goto_ra_dec','low','$ra_hex$,$dec_hex$'),
  858.                 readbool('goto_ra_dec','returns',true),
  859.                 readstring('goto_ra_dec','valid','$valid=#$'),
  860.                 '','');
  861.  
  862.             create_command_record('goto_az_alt',
  863.                 readstring('goto_az_alt','write','B'),
  864.                 readbool('goto_az_alt','append',true),
  865.                 readstring('goto_az_alt','high','$az_hex32$,$alt_hex32$'),
  866.                 readstring('goto_az_alt','low','$az_hex$,$alt_hex$'),
  867.                 readbool('goto_az_alt','returns',true),
  868.                 readstring('goto_az_alt','valid','$valid=#$'),
  869.                 '','');
  870.  
  871.             create_command_record('get_ra_dec_bin',
  872.                 readstring('get_ra_dec_bin','write','E'),
  873.                 readbool('get_ra_dec_bin','append',false),
  874.                 '','',
  875.                 readbool('get_ra_dec_bin','returns',true),
  876.                 readstring('get_ra_dec_bin','high','$ra_bin32$$dec_bin32$'),
  877.                 readstring('get_ra_dec_bin','low','$ra_bin$$dec_bin$'),
  878.                 'ad35,cead#');
  879.  
  880.             create_command_record('get_az_alt_bin',
  881.                 readstring('get_az_alt_bin','write','Z'),
  882.                 readbool('get_az_alt_bin','append',false),
  883.                 '','',
  884.                 readbool('get_az_alt_bin','returns',true),
  885.                 readstring('get_az_alt_bin','high','$az_bin32$$alt_bin32$'),
  886.                 readstring('get_az_alt_bin','low','$az_bin$$alt_bin$'),
  887.                 '12f3,7698#');
  888.  
  889.             create_command_record('goto_az_alt_bin',
  890.                 readstring('goto_az_alt_bin','write','R'),
  891.                 readbool('goto_az_alt_bin','append',true),
  892.                 readstring('goto_az_alt_bin','high','$ra_bin32$$dec_bin32$'),
  893.                 readstring('goto_az_alt_bin','low','$ra_bin$$dec_bin$'),
  894.                 readbool('goto_az_alt_bin','returns',true),
  895.                 readstring('goto_az_alt_bin','valid','$valid=#$'),
  896.                 '','');
  897.  
  898.             create_command_record('goto_az_alt_bin',
  899.                 readstring('goto_az_alt_bin','write','B'),
  900.                 readbool('goto_az_alt_bin','append',true),
  901.                 readstring('goto_az_alt_bin','high','$az_bin32$$alt_bin32$'),
  902.                 readstring('goto_az_alt_bin','low','$az_bin$$alt_bin$'),
  903.                 readbool('goto_az_alt_bin','returns',true),
  904.                 readstring('goto_az_alt_bin','valid','$valid=#$'),
  905.                 '','');
  906.  
  907.             create_command_record('tracking_off',
  908.                 readstring('tracking_off','write','T0'),
  909.                 readbool('tracking_off','append',false),
  910.                 '','',
  911.                 readbool('tracking_off','returns',true),
  912.                 readstring('tracking_off','valid','$valid=#$'),
  913.                 '','');
  914.  
  915.             create_command_record('tracking_az',
  916.                 readstring('tracking_az','write','T1'),
  917.                 readbool('tracking_az','append',false),
  918.                 '','',
  919.                 readbool('tracking_az','returns',true),
  920.                 readstring('tracking_az','valid','$valid=#$'),
  921.                 '','');
  922.  
  923.             create_command_record('tracking_eq_north',
  924.                 readstring('tracking_eq_north','write','T2'),
  925.                 readbool('tracking_eq_north','append',false),
  926.                 '','',
  927.                 readbool('tracking_eq_north','returns',true),
  928.                 readstring('tracking_eq_north','valid','$valid=#$'),
  929.                 '','');
  930.  
  931.             create_command_record('tracking_eq_south',
  932.                 readstring('tracking_eq_south','write','T3'),
  933.                 readbool('tracking_eq_south','append',false),
  934.                 '','',
  935.                 readbool('tracking_eq_south','returns',true),
  936.                 readstring('tracking_eq_south','valid','$valid=#$'),
  937.                 '','');
  938.         end
  939.     else
  940.         begin
  941.             command_last:=nil;
  942.             create_command_record('switch_precision',
  943.                 readstring('switch_precision','write','#:U#'),
  944.                 readbool('switch_precision','append',false),
  945.                 '','',
  946.                 readbool('switch_precision','returns',false),
  947.                 '','','');
  948.             first_command:=command_last;
  949.  
  950.             create_command_record('query',
  951.                 readstring('query','write','#:GR#'),
  952.                 readbool('query','append',false),
  953.                 '','',
  954.                 readbool('query','returns',true),
  955.                 readstring('query','object','$*$'),'',
  956.                 'default test scope');
  957.  
  958.             if scope_type=lx200_type then
  959.                 create_command_record('stopped',
  960.                     readstring('stopped','write',':D#'),
  961.                     readbool('stopped','append',false),
  962.                     '','',
  963.                     readbool('stopped','returns',true),
  964.                     readstring('stopped','valid','$valid=#$'),
  965.                     '','#')
  966.             else create_command_record('stopped',
  967.                 readstring('stopped','write',':D#'),
  968.                 readbool('stopped','append',false),
  969.                 '','',
  970.                 readbool('stopped','returns',true),
  971.                 readstring('stopped','valid','$valid!#$'),
  972.                 '','#');
  973.  
  974.             create_command_record('get_ra',
  975.                 readstring('get_ra','write','#:GR#'),
  976.                 readbool('get_ra','append',false),
  977.                 '','',
  978.                 readbool('get_ra','returns',true),
  979.                 readstring('get_ra','high','$hms$'),
  980.                 readstring('get_ra','low','$hmt$'),
  981.                 '12:08:54');
  982.  
  983.             create_command_record('get_dec',
  984.                 readstring('get_dec','write','#:GD#'),
  985.                 readbool('get_dec','append',false),
  986.                 '','',
  987.                 readbool('get_dec','returns',true),
  988.                 readstring('get_dec','high','$dms$'),
  989.                 readstring('get_dec','low','$dm$'),
  990.                 '+42fl08:59');
  991.  
  992.             create_command_record('get_alt',
  993.                 readstring('get_alt','write','#:GA#'),
  994.                 readbool('get_alt','append',false),
  995.                 '','',
  996.                 readbool('get_alt','returns',true),
  997.                 readstring('get_alt','high','$ams$'),
  998.                 readstring('get_alt','low','$am$'),
  999.                 '15fl46:12');
  1000.  
  1001.             create_command_record('get_az',
  1002.                 readstring('get_az','write','#:GZ#'),
  1003.                 readbool('get_az','append',false),
  1004.                 '','',
  1005.                 readbool('get_az','returns',true),
  1006.                 readstring('get_az','high','$ddms$'),
  1007.                 readstring('get_az','low','$ddmt$'),
  1008.                 'P9fl27:27');
  1009.  
  1010.             create_command_record('set_ra',
  1011.                 readstring('set_ra','write','#:Sr'),
  1012.                 readbool('set_ra','append',true),
  1013.                 readstring('set_ra','high','$hms$#'),
  1014.                 readstring('set_ra','low','$hmt$#'),
  1015.                 readbool('set_ra','returns',true),
  1016.                 readstring('set_ra','valid','$valid=1$'),
  1017.                 '','');
  1018.  
  1019.             create_command_record('set_dec',
  1020.                 readstring('set_dec','write','#:Sd'),
  1021.                 readbool('set_dec','append',true),
  1022.                 readstring('set_dec','high','$dms$#'),
  1023.                 readstring('set_dec','low','$dm$#'),
  1024.                 readbool('set_dec','returns',true),
  1025.                 readstring('set_dec','valid','$valid=1$'),
  1026.                 '','');
  1027.  
  1028.             create_command_record('set_alt',
  1029.                 readstring('set_alt','write','#:Sa'),
  1030.                 readbool('set_alt','append',true),
  1031.                 readstring('set_alt','high','$ams$#'),
  1032.                 readstring('set_alt','low','$am$#'),
  1033.                 readbool('set_alt','returns',true),
  1034.                 readstring('set_alt','valid','$valid=1$'),
  1035.                 '','');
  1036.  
  1037.             create_command_record('set_az',
  1038.                 readstring('set_az','write','#:Sz'),
  1039.                 readbool('set_az','append',true),
  1040.                 readstring('set_az','high','$ddms$#'),
  1041.                 readstring('set_az','low','$ddmt$#'),
  1042.                 readbool('set_az','returns',false),
  1043.                 '','','');
  1044.  
  1045.             create_command_record('slew_ra',
  1046.                 readstring('slew_ra','write','#:MS#'),
  1047.                 readbool('slew_ra','append',false),
  1048.                 '','',
  1049.                 readbool('slew_ra','returns',true),
  1050.                 readstring('slew_ra','valid','$valid=0$'),
  1051.                 '','0');
  1052.  
  1053.             create_command_record('slew_az',
  1054.                 readstring('slew_az','write','#:MA#'),
  1055.                 readbool('slew_az','append',false),
  1056.                 '','',
  1057.                 readbool('slew_az','returns',true),
  1058.                 readstring('slew_az','valid','$valid=0$'),
  1059.                 '','0');
  1060.  
  1061.             create_command_record('sync',
  1062.                 readstring('sync','write','#:CM#'),
  1063.                 readbool('sync','append',false),
  1064.                 '','',
  1065.                 readbool('sync','returns',true),
  1066.                 readstring('sync','object','$*$'),'','');
  1067.  
  1068.             create_command_record('speed_slew',
  1069.                 readstring('speed_slew','write','#:RS#'),
  1070.                 readbool('speed_slew','append',false),
  1071.                 '','',
  1072.                 readbool('speed_slew','returns',false),
  1073.                 '','','');
  1074.  
  1075.             create_command_record('speed_move',
  1076.                 readstring('speed_move','write','#:RM#'),
  1077.                 readbool('speed_move','append',false),
  1078.                 '','',
  1079.                 readbool('speed_move','returns',false),
  1080.                 '','','');
  1081.  
  1082.             create_command_record('speed_guide',
  1083.                 readstring('speed_guide','write','#:RG#'),
  1084.                 readbool('speed_guide','append',false),
  1085.                 '','',
  1086.                 readbool('speed_guide','returns',false),
  1087.                 '','','');
  1088.  
  1089.             create_command_record('speed_center',
  1090.                 readstring('speed_centre','write','#:RC#'),
  1091.                 readbool('speed_centre','append',false),
  1092.                 '','',
  1093.                 readbool('speed_centre','returns',false),
  1094.                 '','','');
  1095.  
  1096.             create_command_record('speed',
  1097.                 readstring('speed','write','#:Sw'),
  1098.                 readbool('speed','append',true),
  1099.                 readstring('speed','speed','$[2-4]$#'),'',
  1100.                 readbool('speed','returns',true),
  1101.                 readstring('speed','value','$*$'),'','');
  1102.  
  1103.             create_command_record('move_north',
  1104.                 readstring('move_north','write','#:Mn#'),
  1105.                 readbool('move_north','append',false),
  1106.                 '','',
  1107.                 readbool('move_north','returns',false),
  1108.                 '','','');
  1109.  
  1110.             create_command_record('move_east',
  1111.                 readstring('move_east','write','#:Me#'),
  1112.                 readbool('move_east','append',false),
  1113.                 '','',
  1114.                 readbool('move_east','returns',false),
  1115.                 '','','');
  1116.  
  1117.             create_command_record('move_south',
  1118.                 readstring('move_south','write','#:Ms#'),
  1119.                 readbool('move_south','append',false),
  1120.                 '','',
  1121.                 readbool('move_south','returns',false),
  1122.                 '','','');
  1123.  
  1124.             create_command_record('move_west',
  1125.                 readstring('move_west','write','#:Mw#'),
  1126.                 readbool('move_west','append',false),
  1127.                 '','',
  1128.                 readbool('move_west','returns',false),
  1129.                 '','','');
  1130.  
  1131.             create_command_record('stop_north',
  1132.                 readstring('stop_north','write','#:Qn#'),
  1133.                 readbool('stop_north','append',false),
  1134.                 '','',
  1135.                 readbool('stop_north','returns',false),
  1136.                 '','','');
  1137.  
  1138.             create_command_record('stop_east',
  1139.                 readstring('stop_east','write','#:Qe#'),
  1140.                 readbool('stop_east','append',false),
  1141.                 '','',
  1142.                 readbool('stop_east','returns',false),
  1143.                 '','','');
  1144.  
  1145.             create_command_record('stop_south',
  1146.                 readstring('stop_south','write','#:Qs#'),
  1147.                 readbool('stop_south','append',false),
  1148.                 '','',
  1149.                 readbool('stop_south','returns',false),
  1150.                 '','','');
  1151.  
  1152.             create_command_record('stop_west',
  1153.                 readstring('stop_west','write','#:Qw#'),
  1154.                 readbool('stop_west','append',false),
  1155.                 '','',
  1156.                 readbool('stop_west','returns',false),
  1157.                 '','','');
  1158.  
  1159.             create_command_record('stop_all',
  1160.                 readstring('stop_all','write','#:Q#'),
  1161.                 readbool('stop_all','append',false),
  1162.                 '','',
  1163.                 readbool('stop_all','returns',false),
  1164.                 '','','');
  1165.  
  1166.             create_command_record('stop_move',
  1167.                 readstring('stop_move','write','#:Q#:Qn#:Qs#:Qe#:Qw#'),
  1168.                 readbool('stop_move','append',false),
  1169.                 '','',
  1170.                 readbool('stop_move','returns',false),
  1171.                 '','','');
  1172.  
  1173.             create_command_record('focus_fast',
  1174.                 readstring('focus_fast','write','#:FF#'),
  1175.                 readbool('focus_fast','append',false),
  1176.                 '','',
  1177.                 readbool('focus_fast','returns',false),
  1178.                 '','','');
  1179.  
  1180.             create_command_record('focus_slow',
  1181.                 readstring('focus_slow','write','#:FS#'),
  1182.                 readbool('focus_slow','append',false),
  1183.                 '','',
  1184.                 readbool('focus_slow','returns',false),
  1185.                 '','','');
  1186.  
  1187.             create_command_record('focus_speed',
  1188.                 readstring('focus_speed','write','#:F'),
  1189.                 readbool('focus_speed','append',true),
  1190.                 readstring('focus_speed','speed','$[1-4]$#'),
  1191.                 '',
  1192.                 readbool('focus_speed','returns',false),
  1193.                 '','','');
  1194.  
  1195.             create_command_record('focus_in',
  1196.                 readstring('focus_in','write','#:F+#'),
  1197.                 readbool('focus_in','append',false),
  1198.                 '','',
  1199.                 readbool('focus_in','returns',false),
  1200.                 '','','');
  1201.  
  1202.             create_command_record('focus_out',
  1203.                 readstring('focus_out','write','#:F-#'),
  1204.                 readbool('focus_out','append',false),
  1205.                 '','',
  1206.                 readbool('focus_out','returns',false),
  1207.                 '','','');
  1208.  
  1209.             create_command_record('focus_stop',
  1210.                 readstring('focus_stop','write','#:FQ#'),
  1211.                 readbool('focus_stop','append',false),
  1212.                 '','',
  1213.                 readbool('focus_stop','returns',false),
  1214.                 '','','');
  1215.  
  1216.             create_command_record('increase_tracking',
  1217.                 readstring('increase_tracking','write','#:T+#'),
  1218.                 readbool('increase_tracking','append',false),
  1219.                 '','',
  1220.                 readbool('increase_tracking','returns',false),
  1221.                 '','','');
  1222.  
  1223.             create_command_record('decrease_tracking',
  1224.                 readstring('decrease_tracking','write','#:T-#'),
  1225.                 readbool('decrease_tracking','append',false),
  1226.                 '','',
  1227.                 readbool('decrease_tracking','returns',false),
  1228.                 '','','');
  1229.  
  1230.             create_command_record('default_tracking',
  1231.                 readstring('default_tracking','write','#:TQ#'),
  1232.                 readbool('default_tracking','append',false),
  1233.                 '','',
  1234.                 readbool('default_tracking','returns',false),
  1235.                 '','','');
  1236.  
  1237.             create_command_record('lunar_tracking',
  1238.                 readstring('lunar_tracking','write','#:TL#'),
  1239.                 readbool('lunar_tracking','append',false),
  1240.                 '','',
  1241.                 readbool('lunar_tracking','returns',false),
  1242.                 '','','');
  1243.  
  1244.         end;
  1245.     command_next:=first_command;
  1246.     command_list:=nil;
  1247.     command_list:=tstringlist.create;
  1248.     while command_next<>nil do
  1249.          with command_list,command_next^ do
  1250.         begin
  1251.             i:=add(command);
  1252.             objects[i]:=tobject(command_next);
  1253.             command_next:=next_command;
  1254.         end;
  1255.     ini_file.free;
  1256. end;
  1257.  
  1258.     { --------------
  1259.         scope commands
  1260.         -------------- }
  1261.  
  1262. function tscope_comms.tell(
  1263.             message_text:string;
  1264.     var return_object:tscope_object)
  1265.     :string;
  1266. var
  1267.     option_names,
  1268.     option_values:tstrings;
  1269.     options_text,
  1270.     option_text,
  1271.     result_text,
  1272.     value_text:widestring;
  1273.     options,
  1274.     done:boolean;
  1275.     arg_i_1:integer;
  1276.     arg_s_1,
  1277.     arg_s_2,
  1278.     arg_s_3,
  1279.     e,s,t,
  1280.     response_text:string;
  1281.     i,j:integer;
  1282.  
  1283.     function parse_out(
  1284.         template:string;
  1285.         value_1,
  1286.         value_2:string)
  1287.         :string;
  1288.     var
  1289.         i,j,k,u,l:integer;
  1290.         b:boolean;
  1291.         f1,f2:double;
  1292.         w1:short;
  1293.         w2:long;
  1294.         sub,
  1295.         r:string;
  1296.         h:hms;
  1297.         d:dms;
  1298.         a:ams;
  1299.  
  1300.         function hexstr(
  1301.             b:double;
  1302.             w:integer)
  1303.             :string;
  1304.         var
  1305.             i,j:integer;
  1306.             t:string;
  1307.             c:char;
  1308.         begin
  1309.             t:=stringofchar('0',w);
  1310.             for i:=w downto 1 do
  1311.                 begin
  1312.                     j:=trunc(b);
  1313.                     j:=j mod 16;
  1314.                     b:=b/16;
  1315.                     c:=chr(j+ord('0'));
  1316.                     if ord(c)>ord('9') then
  1317.                         c:=chr(ord(c)+7);
  1318.                     t[i]:=c;
  1319.                 end;
  1320.             result:=t;
  1321.         end;
  1322.  
  1323.     begin
  1324.         b:=false;
  1325.         f1:=strtofloatdef(value_1,0);
  1326.         f2:=strtofloatdef(value_2,0);
  1327.         i:=1;
  1328.         r:='';
  1329.         result:='';
  1330.         while i<=length(template) do
  1331.             begin
  1332.                 if template[i]='$' then
  1333.                     begin
  1334.                         b:=not b;
  1335.                         inc(i);
  1336.                     end
  1337.                 else if b then
  1338.                      with scope_config do
  1339.                     begin
  1340.                         j:=pos('$',copy(template,i,length(template)));
  1341.                         if j>0 then
  1342.                              with return_object do
  1343.                             begin
  1344.                                 sub:=copy(template,i,j-1);
  1345.                                 { =====
  1346.                                     meade
  1347.                                     ===== }
  1348.                                 { HH:MM:SS }
  1349.                                 if sub='hms' then
  1350.                                     begin
  1351.                                         right_ascension_str(f1,h);
  1352.                                         r:=r+h.high;
  1353.                                     end
  1354.                                 { HH:MM.T# }
  1355.                                 else if sub='hmt' then
  1356.                                     begin
  1357.                                         right_ascension_str(f1,h);
  1358.                                         r:=r+h.low;
  1359.                                     end
  1360.                                 { sDD*MMíSS }
  1361.                                 else if sub='ams' then
  1362.                                     begin
  1363.                                         altitude_str(f1,a);
  1364.                                         r:=r+a.high;
  1365.                                     end
  1366.                                 { sDD*MM }
  1367.                                 else if sub='am' then
  1368.                                     begin
  1369.                                         altitude_str(f1,a);
  1370.                                         r:=r+a.low;
  1371.                                     end
  1372.                                 { sDD*MM'SS }
  1373.                                 else if sub='dms' then
  1374.                                     begin
  1375.                                         declination_str(f1,d);
  1376.                                         r:=r+d.high;
  1377.                                     end
  1378.                                 { sDD*MM }
  1379.                                 else if sub='dm' then
  1380.                                     begin
  1381.                                         declination_str(f1,d);
  1382.                                         r:=r+d.low;
  1383.                                     end
  1384.                                 { DDD*MMíSS }
  1385.                                 else if sub='ddms' then
  1386.                                     begin
  1387.                                         azimuth_str(f1,d);
  1388.                                         r:=r+d.high;
  1389.                                     end
  1390.                                 { DDD*MM#T }
  1391.                                 else if sub='ddmt' then
  1392.                                     begin
  1393.                                         azimuth_str(f1,d);
  1394.                                         r:=r+d.low;
  1395.                                     end
  1396.                                 { =========
  1397.                                     celestron
  1398.                                     ========= }
  1399.                                 else if sub='az_bin' then
  1400.                                     begin
  1401.                                         w1:=short(word(trunc(f1/degrees_in_quarter*hex_16_r)));
  1402.                                         r:=r+chr(w1[2])+chr(w1[1]);
  1403.                                     end
  1404.                                 else if sub='az_hex' then
  1405.                                     r:=r+hexstr(f1/minutes_in_circle*hex_16_r,hex_16)
  1406.                                 else if sub='az_bin32' then
  1407.                                     begin
  1408.                                         w2:=long(cardinal(
  1409.                                             trunc(f1/degrees_in_quarter*hex_32_r)));
  1410.                                         r:=r+chr(w2[4])+chr(w2[3])+chr(w2[2])+chr(w2[1]);
  1411.                                     end
  1412.                                 else if sub='az_hex32' then
  1413.                                     r:=r+hexstr(f1/minutes_in_circle*hex_32_r,hex_16)
  1414.                                 else if sub='alt_bin' then
  1415.                                     begin
  1416.                                         w1:=short(word(
  1417.                                             trunc(f2/degrees_in_quarter*hex_16_r)));
  1418.                                         r:=r+chr(w1[2])+chr(w1[1]);
  1419.                                     end
  1420.                                 else if sub='alt_hex' then
  1421.                                     r:=r+hexstr(f2/minutes_in_circle*hex_16_r,hex_16)
  1422.                                 else if sub='alt_bin32' then
  1423.                                     begin
  1424.                                         w2:=long(cardinal(
  1425.                                             trunc(f2/degrees_in_quarter*hex_32_r)));
  1426.                                         r:=r+chr(w2[4])+chr(w2[3])+chr(w2[2])+chr(w2[1]);
  1427.                                     end
  1428.                                 else if sub='alt_hex32' then
  1429.                                     r:=r+hexstr(f2/minutes_in_circle*hex_32_r,hex_16)
  1430.                                 else if sub='ra_bin' then
  1431.                                     begin
  1432.                                         w1:=short(word(
  1433.                                             trunc(f1/hours_in_circle*hex_16_r)));
  1434.                                         r:=r+chr(w1[2])+chr(w1[1]);
  1435.                                     end
  1436.                                 else if sub='ra_hex' then
  1437.                                     r:=r+hexstr(f1/hours_minutes_in_circle*hex_16_r,hex_16)
  1438.                                 else if sub='ra_bin32' then
  1439.                                     begin
  1440.                                         w2:=long(cardinal(
  1441.                                             trunc(f1/hours_in_circle*hex_32_r)));
  1442.                                         r:=r+chr(w2[4])+chr(w2[3])+chr(w2[2])+chr(w2[1]);
  1443.                                     end
  1444.                                 else if sub='ra_hex32' then
  1445.                                     r:=r+hexstr(f1/hours_minutes_in_circle*hex_32_r,hex_16)
  1446.                                 else if sub='dec_bin' then
  1447.                                     begin
  1448.                                         w1:=short(word(
  1449.                                             trunc(f2/degrees_in_quarter*hex_16_r)));
  1450.                                         r:=r+chr(w1[2])+chr(w1[1]);
  1451.                                     end
  1452.                                 else if sub='dec_hex' then
  1453.                                     r:=r+hexstr(f2/minutes_in_circle*hex_16_r,hex_16)
  1454.                                 else if sub='dec_bin32' then
  1455.                                     begin
  1456.                                         w2:=long(cardinal(
  1457.                                             trunc(f2/degrees_in_quarter*hex_32_r)));
  1458.                                         r:=r+chr(w2[4])+chr(w2[3])+chr(w2[2])+chr(w2[1]);
  1459.                                     end
  1460.                                 else if sub='dec_hex32' then
  1461.                                     r:=r+hexstr(f2/minutes_in_circle*hex_32_r,hex_16)
  1462.                                 else if sub[1]='[' then
  1463.                                     begin
  1464.                                         k:=strtointdef(value_1,-1);
  1465.                                         result:='fail : value out of range';
  1466.                                         if k>=0 then
  1467.                                             begin
  1468.                                                 l:=strtointdef(sub[2],-1);
  1469.                                                 if l>=0 then
  1470.                                                     begin
  1471.                                                         u:=strtointdef(sub[4],-1);
  1472.                                                         if u>=0 then
  1473.                                                             begin
  1474.                                                                 if k<l then
  1475.                                                                     r:=r+inttostr(l)
  1476.                                                                 else if k>u then
  1477.                                                                     r:=r+inttostr(u)
  1478.                                                                 else
  1479.                                                                     r:=r+value_1;
  1480.                                                             end
  1481.                                                         else
  1482.                                                             exit;
  1483.                                                     end
  1484.                                                 else
  1485.                                                     exit;
  1486.                                             end
  1487.                                         else
  1488.                                             exit;
  1489.                                     end
  1490.                                 else
  1491.                                     begin
  1492.                                         result:='fail : unknown template : '+sub;
  1493.                                         exit;
  1494.                                     end;
  1495.                                 inc(i,j-1);
  1496.                             end
  1497.                         else
  1498.                             begin
  1499.                                 result:='fail : missing closing $';
  1500.                                 exit;
  1501.                             end;
  1502.                     end
  1503.                 else if template<>'' then
  1504.                     begin
  1505.                         r:=r+template[i];
  1506.                         inc(i);
  1507.                     end
  1508.                 else
  1509.                     begin
  1510.                         result:='fail : end of template';
  1511.                         exit;
  1512.                     end;
  1513.             end;
  1514.         result:=r;
  1515.     end;
  1516.  
  1517.     procedure parse_in(
  1518.                 template:string;
  1519.         var value:string);
  1520.     var
  1521.         i,j,m,w:integer;
  1522.         k,l:double;
  1523.         b:boolean;
  1524.         sub,
  1525.         e,q,r,s,t,x,wb:string;
  1526.         h:hms;
  1527.         d:dms;
  1528.         a:ams;
  1529.  
  1530.         function strtohex(
  1531.             var r:double;
  1532.                     b:integer)
  1533.                     :boolean;
  1534.         var
  1535.             i,j:integer;
  1536.             h:double;
  1537.             t:string;
  1538.         begin
  1539.             t:=copy(q,w,b);
  1540.             inc(w,b);
  1541.             q:=copy(q,w,length(q)-b);
  1542.             h:=1;
  1543.             r:=0;
  1544.             result:=true;
  1545.             for i:=b downto 1 do
  1546.                 begin
  1547.                     j:=ord(t[i]);
  1548.                     if j>ord('9') then
  1549.                         begin
  1550.                             j:=j and $df-ord('0')-7;
  1551.                             if j>=16 then
  1552.                                 begin
  1553.                                     result:=false;
  1554.                                     exit;
  1555.                                 end;
  1556.                         end
  1557.                     else
  1558.                         begin
  1559.                             j:=j-ord('0');
  1560.                             if j<0 then
  1561.                                 begin
  1562.                                     result:=false;
  1563.                                     exit;
  1564.                                 end;
  1565.                         end;
  1566.                     r:=r+trunc(j*h);
  1567.                     h:=h*16;
  1568.                 end;
  1569.         end;
  1570.  
  1571.     begin
  1572.         b:=false;
  1573.         for i:=1 to wb_size do
  1574.             wb:=wb+char(work_buffer[i]);
  1575.         i:=1;
  1576.         w:=1;
  1577.         r:='';
  1578.         q:=wb;
  1579.         x:='';
  1580.         while i<=length(template) do
  1581.             begin
  1582.                 if template[i]='$' then
  1583.                     begin
  1584.                         b:=not b;
  1585.                         inc(i);
  1586.                     end
  1587.                 else if b then
  1588.                      with scope_config do
  1589.                     begin
  1590.                         j:=pos('$',copy(template,i,length(template)));
  1591.                         if j>0 then
  1592.                              with return_object do
  1593.                             begin
  1594.                                 sub:=copy(template,i,j-1);
  1595.                                 h.high:='';
  1596.                                 h.low:='';
  1597.                                 d.high:='';
  1598.                                 d.low:='';
  1599.                                 { =====
  1600.                                     meade
  1601.                                     ===== }
  1602.                                 { HH:MM:SS }
  1603.                                 if sub='hms' then
  1604.                                     begin
  1605.                                         h.high:=copy(q,1,hms_s);
  1606.                                         inc(w,hms_s);
  1607.                                         if not str_right_ascension(h) then
  1608.                                             begin
  1609.                                                 string(value):='fail : incorrect ra : '+sub;
  1610.                                                 exit;
  1611.                                             end
  1612.                                         else
  1613.                                             x:=wb;
  1614.                                     end
  1615.                                 { HH:MM.T# }
  1616.                                 else if sub='hmt' then
  1617.                                     begin
  1618.                                         h.high:=copy(q,1,hmt_s);
  1619.                                         inc(w,hmt_s);
  1620.                                         if not str_right_ascension(h) then
  1621.                                             begin
  1622.                                                 string(value):='fail : incorrect ra : '+sub;
  1623.                                                 exit;
  1624.                                             end
  1625.                                         else
  1626.                                             x:=wb;
  1627.                                     end
  1628.                                 { sDD*MMíSS }
  1629.                                 else if sub='ams' then
  1630.                                     begin
  1631.                                         a.high:=copy(q,1,ams_s);
  1632.                                         inc(w,ams_s);
  1633.                                         if not str_altitude(a) then
  1634.                                             begin
  1635.                                                 string(value):='fail : incorrect alt : '+sub;
  1636.                                                 exit;
  1637.                                             end
  1638.                                         else
  1639.                                             x:=wb;
  1640.                                     end
  1641.                                 { sDD*MM }
  1642.                                 else if sub='am' then
  1643.                                     begin
  1644.                                         a.high:=copy(q,1,am_s);
  1645.                                         inc(w,am_s);
  1646.                                         if not str_altitude(a) then
  1647.                                             begin
  1648.                                                 string(value):='fail : incorrect alt : '+sub;
  1649.                                                 exit;
  1650.                                             end
  1651.                                         else
  1652.                                             x:=wb;
  1653.                                     end
  1654.                                 { sDD*MMíSS }
  1655.                                 else if sub='dms' then
  1656.                                     begin
  1657.                                         d.high:=copy(q,1,dms_s);
  1658.                                         inc(w,dms_s);
  1659.                                         if not str_declination(d) then
  1660.                                             begin
  1661.                                                 string(value):='fail : incorrect dec : '+sub;
  1662.                                                 exit;
  1663.                                             end
  1664.                                         else
  1665.                                             x:=wb;
  1666.                                     end
  1667.                                 { sDD*MM }
  1668.                                 else if sub='dm' then
  1669.                                     begin
  1670.                                         d.high:=copy(q,1,dm_s);
  1671.                                         inc(w,dm_s);
  1672.                                         if not str_declination(d) then
  1673.                                             begin
  1674.                                                 string(value):='fail : incorrect dec : '+sub;
  1675.                                                 exit;
  1676.                                             end
  1677.                                         else
  1678.                                             x:=wb;
  1679.                                     end
  1680.                                 { DDD*MMíSS }
  1681.                                 else if sub='ddms' then
  1682.                                     begin
  1683.                                         d.high:=copy(q,1,ddms_s);
  1684.                                         inc(w,ddms_s);
  1685.                                         if not str_azimuth(d) then
  1686.                                             begin
  1687.                                                 string(value):='fail : incorrect az : '+sub;
  1688.                                                 exit;
  1689.                                             end
  1690.                                         else
  1691.                                             x:=wb;
  1692.                                     end
  1693.                                 { DDD*MM#T }
  1694.                                 else if sub='ddmt' then
  1695.                                     begin
  1696.                                         d.high:=copy(q,1,ddmt_s);
  1697.                                         inc(w,ddmt_s);
  1698.                                         if not str_azimuth(d) then
  1699.                                             begin
  1700.                                                 string(value):='fail : incorrect az : '+sub;
  1701.                                                 exit;
  1702.                                             end
  1703.                                         else
  1704.                                             x:=wb;
  1705.                                     end
  1706.                                 { =========
  1707.                                     celestron
  1708.                                     ========= }
  1709.                                 else if sub='az_bin' then
  1710.                                     begin
  1711.                                         t:=copy(q,w,sizeof(short));
  1712.                                         k:=(byte(t[1])*256+byte(t[2]))/
  1713.                                             hex_16_r*degrees_in_circle;
  1714.                                         return_object.az:=k;
  1715.                                         inc(w,2);
  1716.                                     end
  1717.                                 else if sub='az_hex' then
  1718.                                     begin
  1719.                                         if strtohex(k,hex_16) then
  1720.                                             begin
  1721.                                                 k:=k/hex_16_r*minutes_in_circle;
  1722.                                                 return_object.az:=k;
  1723.                                                 x:='ok';
  1724.                                             end
  1725.                                         else
  1726.                                             begin
  1727.                                                 string(value):='fail : incorrect az : '+sub;
  1728.                                                 exit;
  1729.                                             end;
  1730.                                         inc(w,4);
  1731.                                     end
  1732.                                 else if sub='az_bin32' then
  1733.                                     begin
  1734.                                         t:=copy(q,w,sizeof(long));
  1735.                                         k:=(byte(t[1])*4294967296+
  1736.                                             byte(t[2])*65536+
  1737.                                             byte(t[3])*256+
  1738.                                             byte(t[4]))/hex_32_r*degrees_in_circle;
  1739.                                         return_object.az:=k;
  1740.                                         inc(w,4);
  1741.                                     end
  1742.                                 else if sub='az_hex32' then
  1743.                                     begin
  1744.                                         if strtohex(k,hex_32) then
  1745.                                             begin
  1746.                                                 k:=k/hex_32_r*minutes_in_circle;
  1747.                                                 return_object.az:=k;
  1748.                                                 x:='ok';
  1749.                                             end
  1750.                                         else
  1751.                                             begin
  1752.                                                 string(value):='fail : incorrect az : '+sub;
  1753.                                                 exit;
  1754.                                             end;
  1755.                                         inc(w,8);
  1756.                                     end
  1757.                                 else if sub='alt_bin' then
  1758.                                     begin
  1759.                                         t:=copy(q,w,sizeof(short));
  1760.                                         k:=(byte(t[1])*256+byte(t[2]))/
  1761.                                             hex_16_r*degrees_in_quarter;
  1762.                                         return_object.alt:=k;
  1763.                                         inc(w,2);
  1764.                                     end
  1765.                                 else if sub='alt_hex' then
  1766.                                     begin
  1767.                                         if strtohex(k,hex_16) then
  1768.                                             begin
  1769.                                                 k:=k/hex_16_r*minutes_in_circle;
  1770.                                                 return_object.alt:=k;
  1771.                                                 x:='ok';
  1772.                                             end
  1773.                                         else
  1774.                                             begin
  1775.                                                 string(value):='fail : incorrect alt : '+sub;
  1776.                                                 exit;
  1777.                                             end;
  1778.                                         inc(w,4);
  1779.                                     end
  1780.                                 else if sub='alt_bin32' then
  1781.                                     begin
  1782.                                         t:=copy(q,w,sizeof(long));
  1783.                                         k:=(byte(t[1])*4294967296+
  1784.                                             byte(t[2])*65536+
  1785.                                             byte(t[3])*256+
  1786.                                             byte(t[4]))/hex_32_r*degrees_in_quarter;
  1787.                                         return_object.alt:=k;
  1788.                                         inc(w,4);
  1789.                                     end
  1790.                                 else if sub='alt_hex32' then
  1791.                                     begin
  1792.                                         if strtohex(k,hex_32) then
  1793.                                             begin
  1794.                                                 k:=k/hex_32_r*minutes_in_circle;
  1795.                                                 return_object.alt:=k;
  1796.                                                 x:='ok';
  1797.                                             end
  1798.                                         else
  1799.                                             begin
  1800.                                                 string(value):='fail : incorrect alt : '+sub;
  1801.                                                 exit;
  1802.                                             end;
  1803.                                         inc(w,8);
  1804.                                     end
  1805.                                 else if sub='ra_bin' then
  1806.                                     begin
  1807.                                         t:=copy(q,w,sizeof(short));
  1808.                                         k:=(byte(t[1])*256+byte(t[2]))/
  1809.                                             hex_16_r*hours_in_circle;
  1810.                                         return_object.ra:=k;
  1811.                                         inc(w,2);
  1812.                                     end
  1813.                                 else if sub='ra_hex' then
  1814.                                     begin
  1815.                                         if strtohex(k,hex_16) then
  1816.                                             begin
  1817.                                                 k:=k/hex_16_r*hours_minutes_in_circle;
  1818.                                                 return_object.ra:=k;
  1819.                                                 x:='ok';
  1820.                                             end
  1821.                                         else
  1822.                                             begin
  1823.                                                 string(value):='fail : incorrect ra : '+sub;
  1824.                                                 exit;
  1825.                                             end;
  1826.                                         inc(w,4);
  1827.                                     end
  1828.                                 else if sub='ra_bin32' then
  1829.                                     begin
  1830.                                         t:=copy(q,w,sizeof(long));
  1831.                                         k:=(byte(t[1])*4294967296+
  1832.                                             byte(t[2])*65536+
  1833.                                             byte(t[3])*256+
  1834.                                             byte(t[4]))/hex_32_r*hours_in_circle;
  1835.                                         return_object.ra:=k;
  1836.                                         inc(w,4);
  1837.                                     end
  1838.                                 else if sub='ra_hex32' then
  1839.                                     begin
  1840.                                         if strtohex(k,hex_32) then
  1841.                                             begin
  1842.                                                 k:=k/hex_32_r*hours_minutes_in_circle;
  1843.                                                 return_object.ra:=k;
  1844.                                                 x:='ok';
  1845.                                             end
  1846.                                         else
  1847.                                             begin
  1848.                                                 string(value):='fail : incorrect ra : '+sub;
  1849.                                                 exit;
  1850.                                             end;
  1851.                                         inc(w,8);
  1852.                                     end
  1853.                                 else if sub='dec_bin' then
  1854.                                     begin
  1855.                                         t:=copy(q,w,sizeof(short));
  1856.                                         k:=(byte(t[1])*256+byte(t[2]))/
  1857.                                             hex_16_r*degrees_in_quarter;
  1858.                                         return_object.dec:=k;
  1859.                                         inc(w,2);
  1860.                                     end
  1861.                                 else if sub='dec_hex' then
  1862.                                     begin
  1863.                                         if strtohex(k,hex_16) then
  1864.                                             begin
  1865.                                                 k:=k/hex_16_r*minutes_in_circle;
  1866.                                                 if k>minutes_in_semicircle then
  1867.                                                     k:=minutes_in_circle-k;
  1868.                                                 return_object.dec:=k;
  1869.                                                 x:='ok';
  1870.                                             end
  1871.                                         else
  1872.                                             begin
  1873.                                                 string(value):='fail : incorrect dec : '+sub;
  1874.                                                 exit;
  1875.                                             end;
  1876.                                         inc(w,4);
  1877.                                     end
  1878.                                 else if sub='dec_bin32' then
  1879.                                     begin
  1880.                                         t:=copy(q,w,sizeof(long));
  1881.                                         k:=(byte(t[1])*4294967296+
  1882.                                             byte(t[2])*65536+
  1883.                                             byte(t[3])*256+
  1884.                                             byte(t[4]))/hex_32_r*degrees_in_quarter;
  1885.                                         return_object.dec:=k;
  1886.                                         inc(w,4);
  1887.                                     end
  1888.                                 else if sub='dec_hex32' then
  1889.                                     begin
  1890.                                         if strtohex(k,hex_32) then
  1891.                                             begin
  1892.                                                 k:=k/hex_32_r*minutes_in_circle;
  1893.                                                 if k>minutes_in_semicircle then
  1894.                                                     k:=minutes_in_circle-k;
  1895.                                                 return_object.dec:=k;
  1896.                                                 x:='ok';
  1897.                                             end
  1898.                                         else
  1899.                                             begin
  1900.                                                 string(value):='fail : incorrect dec : '+sub;
  1901.                                                 exit;
  1902.                                             end;
  1903.                                         inc(w,8);
  1904.                                     end
  1905.                                 else if copy(sub,1,5)='valid' then
  1906.                                     begin
  1907.                                         s:=copy(sub,6,length(sub));
  1908.                                         m:=length(q);
  1909.                                         if strtofloatdef(s,-1)>=0 then
  1910.                                             begin
  1911.                                                 while copy(q,1,2)='00' do
  1912.                                                     begin
  1913.                                                         m:=m-1;
  1914.                                                         q:=copy(q,2,length(q));
  1915.                                                     end;
  1916.                                             end;
  1917.                                         t:=copy(q,1,length(s));
  1918.                                         if strtofloatdef(t,-1)>=0 then
  1919.                                             begin
  1920.                                                 while (m>0) and  (t[m]<'0') and (t[m]>'9') do
  1921.                                                     begin
  1922.                                                         m:=m-1;
  1923.                                                         t:=copy(t,1,m);
  1924.                                                     end;
  1925.                                                 e:='';
  1926.                                                 while (length(s)>0) and ((s[1]<'0') or (s[1]>'9')) do
  1927.                                                     begin
  1928.                                                         e:=e+s[1];
  1929.                                                         s:=copy(s,2,length(s));
  1930.                                                     end;
  1931.                                                 if s='' then
  1932.                                                     s:='0';
  1933.                                             end;
  1934.                                         k:=strtofloatdef(s,-1);
  1935.                                         l:=strtofloatdef(t,-1);
  1936.                                         if (k=-1) or (l=-1) then
  1937.                                             begin
  1938.                                                 while pos(' ',q)>0 do
  1939.                                                     q:=copy(q,2,length(q)-1);
  1940.                                                 e:=e+s[1];
  1941.                                                 s:=copy(s,2,length(s));
  1942.                                                 t:=copy(q,1,length(s));
  1943.                                                 if ((e='=') and (s=t)) or
  1944.                                                      ((e='!') and (s<>t)) then
  1945.                                                     r:=r+'true'
  1946.                                                 else
  1947.                                                     r:=r+'false';
  1948.                                             end
  1949.                                         else if ((e='=') and (k=l)) or
  1950.                                              ((e='<>') and (k<>l)) or
  1951.                                              ((e='>=') and (k>=l)) or
  1952.                                              ((e='<=') and (k<=l)) or
  1953.                                              ((e='>') and (k>l)) or
  1954.                                              ((e='<') and (k<l)) then
  1955.                                             r:=r+'true'
  1956.                                         else
  1957.                                             r:=r+'false';
  1958.                                         w:=m;
  1959.                                         if m<length(q) then
  1960.                                             r:=r+'=';
  1961.                                     end
  1962.                                 else if sub[1]='*' then
  1963.                                     begin
  1964.                                         r:=r+q;
  1965.                                         w:=length(q);
  1966.                                         q:='';
  1967.                                     end
  1968.                                 else
  1969.                                     begin
  1970.                                         string(value):='fail : unknown template : '+sub;
  1971.                                         exit;
  1972.                                     end;
  1973.                                 q:=copy(q,w,length(q));
  1974.                                 inc(i,j-1);
  1975.                                 w:=1;
  1976.                             end
  1977.                         else
  1978.                             begin
  1979.                                 string(value):='fail : missing closing $';
  1980.                                 exit;
  1981.                             end;
  1982.                     end
  1983.                 else if (template[i]<>'') and (q[w]<>'') then
  1984.                     begin
  1985.                         if template[i]=q[w] then
  1986.                             begin
  1987.                                 inc(w);
  1988.                                 inc(i);
  1989.                             end
  1990.                         else
  1991.                             begin
  1992.                                 string(value):='fail : mismatched argument';
  1993.                                 exit;
  1994.                             end;
  1995.                     end
  1996.                 else
  1997.                     string(value):='fail : mismatched argument';
  1998.             end;
  1999.         string(value):=x+r;
  2000.     end;
  2001.  
  2002.     function send_command(
  2003.                 scope_command:string;
  2004.                 write_option_1,
  2005.                 write_option_2:string;
  2006.         var read_option:string)
  2007.                 :boolean;
  2008.     var
  2009.         variable_1,
  2010.         variable_2,
  2011.         template:string;
  2012.         scope_command_rec:p_command_record;
  2013.         i,j:integer;
  2014.     begin
  2015.         i:=command_list.indexof(scope_command);
  2016.         result:=true;
  2017.         with scope_network do
  2018.              if i>=0 then
  2019.             begin
  2020.                 scope_command_rec:=p_command_record(command_list.objects[i]);
  2021.                 with scope_command_rec^,scope_config,return_object do
  2022.                     begin
  2023.                         if write_option_1<>'' then
  2024.                             begin
  2025.                                 i:=option_names.indexof(write_option_1);
  2026.                                 j:=option_names.indexof(write_option_2);
  2027.                                 if i>=0 then
  2028.                                     begin
  2029.                                         variable_1:=option_values[i];
  2030.                                         if j>=0 then
  2031.                                             variable_2:=option_values[j]
  2032.                                         else
  2033.                                             variable_2:='';
  2034.                                         if appends then
  2035.                                             begin
  2036.                                                 if out_text_2<>'' then
  2037.                                                     begin
  2038.                                                         if high_precision then
  2039.                                                             template:=out_text_1
  2040.                                                         else
  2041.                                                             template:=out_text_2;
  2042.                                                         e:=parse_out(template,variable_1,variable_2);
  2043.                                                         write_option_1:=scope_write+e;
  2044.                                                     end
  2045.                                                 else
  2046.                                                     begin
  2047.                                                         template:=out_text_1;
  2048.                                                         e:=parse_out(template,variable_1,variable_2);
  2049.                                                         write_option_1:=scope_write+e;
  2050.                                                     end;
  2051.                                                 if pos(e,'fail')=1 then
  2052.                                                     begin
  2053.                                                         result:=false;
  2054.                                                         exit;
  2055.                                                     end
  2056.                                                 else
  2057.                                                     begin
  2058.                                                         result:=write(write_option_1);
  2059.                                                         e:='';
  2060.                                                     end;
  2061.                                             end
  2062.                                         else if not write(scope_write) then
  2063.                                             begin
  2064.                                                 e:='fail : write';
  2065.                                                 result:=false;
  2066.                                                 exit;
  2067.                                             end;
  2068.                                     end
  2069.                                 else
  2070.                                     begin
  2071.                                         e:='fail : scope command not found';
  2072.                                         result:=false;
  2073.                                         exit;
  2074.                                     end;
  2075.                             end
  2076.                         else
  2077.                             result:=write(scope_write);
  2078.                         if returns then
  2079.                             begin
  2080.                                 if read_timeout(default_string) then
  2081.                                     begin
  2082.                                         if in_text_2<>'' then
  2083.                                             begin
  2084.                                                 if high_precision then
  2085.                                                     template:=in_text_1
  2086.                                                 else
  2087.                                                     template:=in_text_2;
  2088.                                                 parse_in(template,e);
  2089.                                             end
  2090.                                         else
  2091.                                             begin
  2092.                                                 template:=in_text_1;
  2093.                                                 parse_in(template,e);
  2094.                                             end;
  2095.                                         if pos('fail',e)<>1 then
  2096.                                             begin
  2097.                                                 read_option:=e;
  2098.                                                 e:='';
  2099.                                                 result:=true;
  2100.                                             end
  2101.                                         else
  2102.                                             result:=false;
  2103.                                     end
  2104.                                 else
  2105.                                     begin
  2106.                                         result:=false;
  2107.                                         e:='fail : read from scope failed';
  2108.                                     end;
  2109.                             end;
  2110.                     end;
  2111.             end
  2112.         else
  2113.             begin
  2114.                 result:=false;
  2115.                 e:='fail : '+scope_control.scope_name+' doesnt support '+scope_command;
  2116.             end;
  2117.     end;
  2118.  
  2119.     function find_option(
  2120.                 option:string;
  2121.         var variable:string)
  2122.         :boolean;
  2123.     begin
  2124.         i:=option_names.indexof(option);
  2125.         if i>=0 then
  2126.             begin
  2127.                 variable:=option_values[i];
  2128.                 result:=true;
  2129.             end
  2130.         else
  2131.             result:=false;
  2132.     end;
  2133.  
  2134.     procedure add_option(
  2135.         name,
  2136.         value:string;
  2137.         bracket:boolean);
  2138.     begin
  2139.         result_text:=result_text+name+'='+value;
  2140.         if not bracket then
  2141.             result_text:=result_text+',';
  2142.     end;
  2143.  
  2144.     function tell_scope
  2145.         :string;
  2146.     begin
  2147.         result:='ok';
  2148.         response_text:='ok';
  2149.         e:='';
  2150.         result_text:='';
  2151.         trim(message_text);
  2152.         return_object:=tscope_object.create;
  2153.         i:=pos('(',message_text);
  2154.         if i>0 then
  2155.             begin
  2156.                 options:=true;
  2157.                 options_text:=copy(message_text,i+1,length(message_text));
  2158.                 if options_text[length(options_text)]<>')' then
  2159.                     begin
  2160.                         update_status_log('no closing ) : '+message_text);
  2161.                         exit;
  2162.                     end;
  2163.                 options_text:=copy(options_text,1,length(options_text)-1)+',';
  2164.                 option_names:=tstringlist.create;
  2165.                 option_values:=tstringlist.create;
  2166.                 message_text:=copy(message_text,1,i-1);
  2167.                 done:=false;
  2168.                 while not done do
  2169.                     begin
  2170.                         i:=pos(',',options_text);
  2171.                         if i>0 then
  2172.                             begin
  2173.                                 option_text:=copy(options_text,1,i-1);
  2174.                                 options_text:=copy(options_text,i+1,length(options_text));
  2175.                                 j:=pos('=',option_text);
  2176.                                 if j>0 then
  2177.                                     begin
  2178.                                         value_text:=copy(option_text,j+1,length(option_text));
  2179.                                         option_text:=copy(option_text,1,j-1);
  2180.                                     end
  2181.                                 else
  2182.                                     value_text:='';
  2183.                                 option_names.add(option_text);
  2184.                                 option_values.add(value_text);
  2185.                             end
  2186.                         else
  2187.                             done:=true;
  2188.                     end;
  2189.             end
  2190.         else
  2191.             begin
  2192.                 options:=false;
  2193.                 option_names:=nil;
  2194.                 option_values:=nil;
  2195.             end;
  2196.         update_status_log('tell >>');
  2197.         with scope_network,scope_config,return_object do
  2198.             begin
  2199.                 if message_text='connect' then
  2200.                     begin
  2201.                         update_status_log_header('connect');
  2202.                         if not connect_to_scope then
  2203.                             response_text:='fail : no connection'
  2204.                         else if scope_type=celestron_type then
  2205.                             begin
  2206.                                 if (binary_mode and send_command('get_ra_dec_bin','','',t)) or
  2207.                                      (not binary_mode and send_command('get_ra_dec','','',t)) then
  2208.                                     scope_info.show_info
  2209.                                 else
  2210.                                     e:='Scope not talking';
  2211.                             end
  2212.                         else if send_command('query','','',t) then
  2213.                             begin
  2214.                                 if t<>'' then
  2215.                                     high_precision:=pos('.',t)<=0
  2216.                                 else
  2217.                                     e:='scope not talking';
  2218.                             end
  2219.                         else
  2220.                             disconnect_from_scope;
  2221.                     end
  2222.                 else if message_text='disconnect' then
  2223.                     begin
  2224.                         update_status_log_header('disconnect');
  2225.                         if not disconnect_from_scope then
  2226.                             response_text:='fail : cant disconnect';
  2227.                     end
  2228.                 else if message_text='align' then
  2229.                     begin
  2230.                         update_status_log_header('align');
  2231.                         if send_command('set_ra','ra','',t) and
  2232.                              send_command('set_dec','dec','',t) then
  2233.                             send_command('sync','','',info);
  2234.                     end
  2235.                 else if message_text='get_ra_dec' then
  2236.                     begin
  2237.                         update_status_log_header('get_ra_dec');
  2238.                         if scope_type=celestron_type then
  2239.                             begin
  2240.                                 if (binary_mode and send_command('get_ra_dec_bin','','',t)) or
  2241.                                      (not binary_mode and send_command('get_ra_dec','','',t)) then
  2242.                                     begin
  2243.                                         if high_precision then
  2244.                                             add_option('precision','high',true)
  2245.                                         else
  2246.                                             add_option('precision','low',true);
  2247.                                     end;
  2248.                             end
  2249.                         else if send_command('get_ra','','',t) then
  2250.                             begin
  2251.                                 if send_command('get_dec','','',t) then
  2252.                                     begin
  2253.                                         if high_precision then
  2254.                                             add_option('precision','high',true)
  2255.                                         else
  2256.                                             add_option('precision','low',true);
  2257.                                     end;
  2258.                             end;
  2259.                     end
  2260.                 else if message_text='get_az_alt' then
  2261.                     begin
  2262.                         update_status_log_header('get_az_alt');
  2263.                         if scope_type=celestron_type then
  2264.                             begin
  2265.                                 if (binary_mode and send_command('get_az_alt_bin','','',t)) or
  2266.                                      (not binary_mode and send_command('get_az_alt','','',t)) then
  2267.                                     begin
  2268.                                         if high_precision then
  2269.                                             add_option('precision','high',true)
  2270.                                         else
  2271.                                             add_option('precision','low',true);
  2272.                                     end;
  2273.                             end
  2274.                         else if send_command('get_az','','',t) then
  2275.                             begin
  2276.                                 if send_command('get_alt','','',t) then
  2277.                                     begin
  2278.                                         if high_precision then
  2279.                                             add_option('precision','high',true)
  2280.                                         else
  2281.                                             add_option('precision','low',true);
  2282.                                     end;
  2283.                             end;
  2284.                     end
  2285.                 else if message_text='switch_precision' then
  2286.                     begin
  2287.                         update_status_log_header('switch_precision');
  2288.                         send_command('switch_precision','','',t);
  2289.                     end
  2290.                 else if message_text='focus_speed' then
  2291.                     begin
  2292.                         update_status_log_header(message_text);
  2293.                         send_command(message_text,'speed','',t);
  2294.                     end
  2295.                 else if message_text='focus' then
  2296.                      with scope_focus do
  2297.                     begin
  2298.                         update_status_log_header('focus');
  2299.                         if find_option('dir',arg_s_1) and
  2300.                              find_option('speed',arg_s_2) and
  2301.                              find_option('timeout',arg_s_3) then
  2302.                             begin
  2303.                                 if strtointdef(arg_s_2,0)>focus_speeds/max_speeds then
  2304.                                     done:=send_command('focus_fast','','',t)
  2305.                                 else
  2306.                                     done:=send_command('focus_slow','','',t);
  2307.                                 if not done then
  2308.                                     response_text:='fail'
  2309.                                 else
  2310.                                     begin
  2311.                                         arg_i_1:=strtointdef(arg_s_3,min_timeout);
  2312.                                         if arg_i_1<min_timeout then
  2313.                                             arg_i_1:=min_timeout
  2314.                                         else if arg_i_1>max_timeout then
  2315.                                             arg_i_1:=max_timeout;
  2316.                                         if arg_s_1='+' then
  2317.                                             s:='focus_in'
  2318.                                         else if arg_s_1='-' then
  2319.                                             s:='focus_out'
  2320.                                         else
  2321.                                             response_text:='fail : unknown operand : '+arg_s_1;
  2322.                                     end;
  2323.                             end
  2324.                         else
  2325.                             response_text:='fail : cant find argument : dir';
  2326.                         if (pos('fail',response_text)<>1) and
  2327.                              not send_command(s,'','',t) then
  2328.                             update_status_log_failed
  2329.                         else if scope_enabled then
  2330.                             begin
  2331.                                 focus_timeout:=arg_i_1;
  2332.                                 enable_focus_timer;
  2333.                             end;
  2334.                     end
  2335.                 else if message_text='stop_focus' then
  2336.                     begin
  2337.                         update_status_log_header('stop_focus');
  2338.                         send_command('focus_stop','','',t);
  2339.                     end
  2340.                 else if message_text='goto_ra_dec' then
  2341.                     begin
  2342.                         update_status_log_header('goto_ra_dec');
  2343.                         if scope_type=celestron_type then
  2344.                             begin
  2345.                                 if (binary_mode and
  2346.                                         not send_command('goto_ra_dec_bin','ra','dec',t)) or
  2347.                                      (not binary_mode and
  2348.                                         not send_command('goto_ra_dec','ra','dec',t)) then
  2349.                                     response_text:='fail : ';
  2350.                             end
  2351.                         else
  2352.                             begin
  2353.                                 if send_command('set_ra','ra','',t) and
  2354.                                      send_command('set_dec','dec','',t) and
  2355.                                      send_command('slew_ra','','',t) and
  2356.                                      (t<>'true') then
  2357.                                     response_text:='fail : ';
  2358.                             end;
  2359.                     end
  2360.                 else if message_text='goto_az_alt' then
  2361.                     begin
  2362.                         update_status_log_header('goto_az_alt');
  2363.                         if scope_type=celestron_type then
  2364.                             begin
  2365.                                 if (binary_mode and
  2366.                                         not send_command('goto_ra_dec_bin','az','alt',t)) or
  2367.                                      (not binary_mode and
  2368.                                         not send_command('goto_ra_dec','az','alt',t)) then
  2369.                                     response_text:='fail : ';
  2370.                             end
  2371.                         else
  2372.                             begin
  2373.                                 if send_command('set_az','az','',t) and
  2374.                                      send_command('set_alt','alt','',t) and
  2375.                                      send_command('slew_az','','',t) and
  2376.                                      (t<>'true') then
  2377.                                     response_text:='fail : ';
  2378.                             end;
  2379.                     end
  2380.                 else if message_text='stopped' then
  2381.                     begin
  2382.                         update_status_log_header('stopped');
  2383.                         if not send_command('stopped','','',t) then
  2384.                             response_text:='fail : '
  2385.                         else
  2386.                             moving:=t='false';
  2387.                     end
  2388.                 else if message_text='stop_all' then
  2389.                     begin
  2390.                         update_status_log_header(message_text);
  2391.                         send_command(message_text,'','',t);
  2392.                     end
  2393.                 else if (message_text='increase_tracking') or
  2394.                                 (message_text='decrease_tracking') or
  2395.                                 (message_text='default_tracking') or
  2396.                                 (message_text='lunar_tracking') then
  2397.                     begin
  2398.                         update_status_log_header(message_text);
  2399.                         send_command(message_text,'','',t);
  2400.                     end
  2401.                 else if message_text='query' then
  2402.                     begin
  2403.                         update_status_log_header('query');
  2404.                         if not send_command('query','','',t) then
  2405.                             response_text:='fail : ';
  2406.                     end;
  2407.             end;
  2408.         if e<>'' then
  2409.             begin
  2410.                 update_status_log('!!! failed !!!');
  2411.                 update_status_log(e);
  2412.                 response_text:=e;
  2413.             end;
  2414.         update_status_log('<< tell');
  2415.         result:=response_text;
  2416.     end;
  2417.  
  2418. begin
  2419.     result:=tell_scope;
  2420.     if options then
  2421.         begin
  2422.             option_names.free;
  2423.             option_values.free;
  2424.         end;
  2425. end;
  2426.  
  2427.     { ------
  2428.         events
  2429.         ------ }
  2430.  
  2431. procedure tscope_comms.FormShow(
  2432.     Sender: TObject);
  2433. begin
  2434.     with dimensions do
  2435.         begin
  2436.             top:=form_top;
  2437.             left:=form_left;
  2438.         end;
  2439. end;
  2440.  
  2441. procedure tscope_comms.adjust;
  2442. begin
  2443.     with dimensions do
  2444.         begin
  2445.             form_top:=trunc(form_top/last_screen_height*current_height);
  2446.             form_left:=trunc(form_left/last_screen_width*current_width);
  2447.         end;
  2448.     if visible then
  2449.         show;
  2450. end;
  2451.  
  2452. procedure tscope_comms.check_visible_and_show_hide(
  2453.     sender:tobject);
  2454. begin
  2455.     if visible then
  2456.         hide_form
  2457.     else
  2458.         show_form;
  2459.     scope.show_hide(sender,visible);
  2460. end;
  2461.  
  2462. procedure tscope_comms.hide_form;
  2463. begin
  2464.     with dimensions do
  2465.         begin
  2466.             form_top:=top;
  2467.             form_left:=left;
  2468.         end;
  2469.     Visible:=false;
  2470. end;
  2471.  
  2472. procedure tscope_comms.show_form;
  2473. begin
  2474.     Visible:=true;
  2475. end;
  2476.  
  2477. procedure Tscope_comms.check_activate(
  2478.     Sender: TObject);
  2479. begin
  2480.     scope.form_activate(scope_comms,@dimensions);
  2481. end;
  2482.  
  2483. procedure Tscope_comms.form_close_query(
  2484.             Sender: TObject;
  2485.     var CanClose: Boolean);
  2486. begin
  2487.     canclose:=false;
  2488.     visible:=false;
  2489.     with dimensions do
  2490.         begin
  2491.             form_top:=top;
  2492.             form_left:=left;
  2493.         end;
  2494. end;
  2495.  
  2496. procedure Tscope_comms.timeout_editChange(
  2497.     Sender: TObject);
  2498. begin
  2499.     timeout:=strtointdef(timeout_edit.text,1000);
  2500. end;
  2501.  
  2502. procedure Tscope_comms.interval_editChange(
  2503.     Sender: TObject);
  2504. begin
  2505.     interval:=strtointdef(interval_edit.text,100);
  2506. end;
  2507.  
  2508.     { ----------------
  2509.         response timeout
  2510.         ---------------- }
  2511.  
  2512. procedure Tscope_comms.response_timerTimer(
  2513.     Sender: TObject);
  2514. begin
  2515.     if scope_search.search_timer.enabled then
  2516.         scope_search.disable_timer;
  2517.     response_timer.enabled:=false;
  2518.     response_timed_out:=true;
  2519. end;
  2520.  
  2521. end.
  2522.